package com.seguriapp.alerts.gwt.server;

import static com.google.common.collect.Lists.newArrayList;

import java.util.List;

import net.customware.gwt.dispatch.server.ExecutionContext;
import net.customware.gwt.dispatch.shared.DispatchException;
import net.sf.json.JSONArray;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;

import org.apache.log4j.Logger;
import org.restlet.resource.ClientResource;

import com.seguriapp.alerts.gwt.shared.GetAlertsDataAction;
import com.seguriapp.alerts.gwt.shared.GetAlertsDataResult;
import com.seguriapp.common.config.GlobalConfigLoader;
import com.seguriapp.common.gwt.server.AbstractSeguriAppHandler;
import com.seguriapp.common.security.SeguriAppSession;
import com.seguriapp.common.security.SeguriAppSession.Key;
import com.seguriapp.common.security.SeguriAppUser;
import com.seguriapp.entities.Alert;
import com.seguriapp.entities.User;
import com.seguriapp.util.Util;

public class GetAlertsDataHandler extends AbstractSeguriAppHandler<GetAlertsDataAction, GetAlertsDataResult> {

  private static final Logger LOGGER = Logger.getLogger(GetAlertsDataHandler.class);

  public Class<GetAlertsDataAction> getActionType() {
    return GetAlertsDataAction.class;
  }

  public GetAlertsDataResult execute(final GetAlertsDataAction action, final ExecutionContext context) throws DispatchException {

    final GetAlertsDataResult result = new GetAlertsDataResult();
    try {
      final String url = GlobalConfigLoader.getInstance().getGlobalConfig().getBackEndUrl().concat(GlobalConfigLoader.getInstance().getGlobalConfig().getAlertList());
      final ClientResource resource = new ClientResource(url);
      final String alertListJs = resource.post(convertDataToJsonString(action)).getText();
      LOGGER.info("Data received : \n" + alertListJs);
      result.setAlertList(getJsonDataFromString(alertListJs));
      result.setCurrentPage(action.getPage());
      result.setMaxPages(GlobalConfigLoader.getInstance().getGlobalConfig().getMaxPages());
      result.setTotalPages(getJsonTotalPages(alertListJs));
    } catch (Exception e) {
      LOGGER.error("Error obtaining the alerts list", e);
    }
    return result;
  }

  private String convertDataToJsonString(final GetAlertsDataAction action) {
    final JSONObject obj = new JSONObject();
    try {
      obj.put("startDate", Util.parseDateToString(action.getStartDate()));
      obj.put("endDate", Util.parseDateToString(action.getEndDate()));
      obj.put("latitude", action.getLatitude());
      obj.put("longitude", action.getLongitude());
      obj.put("names", action.getNames());
      obj.put("distance", action.getDistance());
      obj.put("policeStationId", action.getPoliceStationId());
      obj.put("searchByPolStation", action.isSearchByPolStation());
      obj.put("page", action.getPage());
      obj.put("pageSize", GlobalConfigLoader.getInstance().getGlobalConfig().getPageSize());
      obj.put("ascending", action.isAscending());
      obj.put("columnSort", action.getColumnSort());
      final User user = SeguriAppUser.getSeguriAppSecureUser().getSeguriAppUser();
      if (user != null) {
        obj.put("userId", user.getId());
      }
    } catch (JSONException e) {
      LOGGER.error("Error al convertir parametros de busqueda a json", e);
    }
    LOGGER.info("Sending Data : \n" + obj.toString());
    return obj.toString();
  }

  private long getJsonTotalPages(final String alertListJs) {
    long totalPages = 0;
    final JSONObject root = JSONObject.fromObject(alertListJs);
    if (root.has("totalPages")) {
      totalPages = root.getLong("totalPages");
    }
    return totalPages;
  }

  private List<Alert> getJsonDataFromString(final String alertListJs) {
    final SeguriAppSession session = SeguriAppUser.getSeguriAppSecureUser().getSeguriAppSession();
    final List<Alert> alertsList = newArrayList();
    final JSONObject root = JSONObject.fromObject(alertListJs);
    JSONArray dataArray = null;
    JSONObject jo = null;
    if (root.has("alerts")) {
      dataArray = root.getJSONArray("alerts");
      if (dataArray != null) {
        final Long lastAlertId = (Long) session.get(Key.LastAlertId);
        Long alertId = lastAlertId != null ? lastAlertId : 0L;
        for (int i = 0; i < dataArray.size(); i++) {
          jo = dataArray.getJSONObject(i);
          final Alert alert = processjSONObject(jo);
          alertsList.add(alert);
          if (alert.getId().compareTo(alertId) > 0) {
            alertId = alert.getId();
          }
          if (lastAlertId != null && alert.getId().compareTo(lastAlertId) > 0) {
            alert.setNewAlert(true);
          }
        }
        if (lastAlertId == null || (lastAlertId != null && alertId.compareTo(lastAlertId) > 0)) {
          session.put(Key.LastAlertId, alertId);
        }
      }
    }
    LOGGER.info("Last Alert ID : " + session.get(Key.LastAlertId));
    return alertsList;
  }

  private Alert processjSONObject(final JSONObject jo) {
    if (jo.has("id") && jo.has("date") && jo.has("longitude") && jo.has("latitude")) {
      final Alert alert = new Alert();
      alert.setDate(Util.parseStringToDate(jo.getString("date")));
      alert.setDni(jo.getString("dni"));
      alert.setId(jo.getLong("id"));
      alert.setLastNames(jo.getString("lastNames"));
      alert.setNames(jo.getString("names"));
      alert.setPhone(jo.getString("phone"));
      alert.setLatitude(jo.getDouble("latitude"));
      alert.setLongitude(jo.getDouble("longitude"));
      return alert;
    }
    return null;
  }

}
